﻿using Painter.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Painter.Component
{
    public class ScaleBorder : Border, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public static DependencyProperty ScaleProperty =
            DependencyProperty.Register("Scale", typeof(double), typeof(ScaleBorder), new PropertyMetadata(1.0));

        protected Point _current_point = new Point(0, 0);
        public int SliderValue
        {
            get { return (int)((double)GetValue(ScaleProperty) >= 1 ? (double)GetValue(ScaleProperty) : -1.0 / (double)GetValue(ScaleProperty)); }
        }
        public string SliderTextValue
        {
            get { return (double)GetValue(ScaleProperty) * 100 + "%"; }
        }
        public int Interval
        {
            get
            {
                if (Scale >= 2 && Scale <= 3) return 100 / 2;
                else if (Scale >= 4 && Scale <= 6) return 100 / 5;
                else if (Scale >= 7 && Scale <= 10) return 100 / 10;
                else return 100;
            }
        }
        public double Scale
        {
            get { return (double)GetValue(ScaleProperty); }
            set
            {
                SetValue(ScaleProperty, value);
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SliderValue"));
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SliderTextValue"));
                InvalidateVisual();
            }
        }
        public Point CurPos
        {
            get
            {
                GroupScroll content = Child as GroupScroll;
                Thickness margin = (content.Content as FrameworkElement)?.Margin ?? new Thickness(0);
                Point pos = _current_point;
                return new Point() {
                    X = Math.Floor((pos.X - BorderThickness.Top - margin.Top < 0 ? 0 : pos.X - BorderThickness.Top - margin.Top) / Scale),
                    Y = Math.Floor((pos.Y - BorderThickness.Left - margin.Left < 0 ? 0 : pos.Y - BorderThickness.Left - margin.Left) / Scale),
                };
            }
        }
        public ScaleBorder()
        {
            HorizontalAlignment = HorizontalAlignment.Left;
            VerticalAlignment = VerticalAlignment.Top;
        }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            _current_point = e.GetPosition(this);
            GroupScroll content = Child as GroupScroll;
            _current_point.Offset(content.ScrollInfo.HorizontalOffset, content.ScrollInfo.VerticalOffset);
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("CurPos"));
            this.InvalidateVisual();
        }
        protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
        {
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                ScaleData scale_data = ScaleData.Find_CreateScaleData(this);
                Scale = scale_data.ZoomInOut(e.Delta < 0);
            }
        }
        protected override Size MeasureOverride(Size arrangeSize)
        {
            FrameworkElement content = Child as FrameworkElement;
            ScaleData scale_data = ScaleData.Find_CreateScaleData(this);
            Thickness margin = ((Child as ContentControl).Content as FrameworkElement)?.Margin ?? new Thickness(0);

            if (double.IsNaN(content.Width)) scale_data.BaseWidth = arrangeSize.Width - BorderThickness.Left - margin.Left-margin.Right;
            if (double.IsNaN(content.Height)) scale_data.BaseHeight = arrangeSize.Height - BorderThickness.Top - margin.Top-margin.Bottom;

            content.Width = arrangeSize.Width - BorderThickness.Left;
            content.Height = arrangeSize.Height - BorderThickness.Top;
            scale_data.UpdateWidthHeight();

            return base.MeasureOverride(arrangeSize);
        }
        protected override void OnRender(DrawingContext dc)
        {
            base.OnRender(dc);
            GroupScroll content = Child as GroupScroll;
            dc.PushTransform(new TranslateTransform(-content.ScrollInfo.HorizontalOffset, -content.ScrollInfo.VerticalOffset));

            Point topLeft = new Point(BorderThickness.Left, BorderThickness.Top);
            Point topRight = new Point(BorderThickness.Left + ActualWidth, BorderThickness.Top);
            Point bottomLeft = new Point(BorderThickness.Left, BorderThickness.Top + ActualHeight);

            topLeft.Offset(content.ScrollInfo.HorizontalOffset, content.ScrollInfo.VerticalOffset);
            topRight.Offset(content.ScrollInfo.HorizontalOffset, content.ScrollInfo.VerticalOffset);
            bottomLeft.Offset(content.ScrollInfo.HorizontalOffset, content.ScrollInfo.VerticalOffset);
            dc.PushClip(new RectangleGeometry(
                new Rect(new Point(content.ScrollInfo.HorizontalOffset, content.ScrollInfo.VerticalOffset),
                new Size(content.Width,content.Height))));

            Thickness margin = ((Child as ContentControl).Content as FrameworkElement)?.Margin ?? new Thickness(0);
            Point contetn_topLeft = new Point(BorderThickness.Left + margin.Left, BorderThickness.Top + margin.Top);
            Point contetn_topRight = new Point(BorderThickness.Left + margin.Left + ActualWidth, BorderThickness.Top + margin.Top);
            Point contetn_bottomLeft = new Point(BorderThickness.Left + margin.Left, BorderThickness.Top + margin.Top + ActualHeight);

            dc.DrawLine(new Pen(new SolidColorBrush(Colors.Black), 0.1),topLeft,topRight);
            dc.DrawLine(new Pen(new SolidColorBrush(Colors.Black), 0.1),topLeft,bottomLeft);

            if (topLeft.X > 10)
            {//竖线
                dc.DrawLine(new Pen(new SolidColorBrush(Colors.Red), 1),
                    new Point(_current_point.X >= contetn_topLeft.X ? _current_point.X : contetn_topLeft.X, 0+ content.ScrollInfo.VerticalOffset),
                    new Point(_current_point.X >= contetn_topLeft.X ? _current_point.X : contetn_topLeft.X, BorderThickness.Top+ content.ScrollInfo.VerticalOffset));
                for (double i = contetn_topLeft.X; i < ActualWidth+ content.ScrollInfo.HorizontalOffset; i += 10)
                {
                    dc.DrawLine(new Pen(new SolidColorBrush(Colors.Black), 0.1),
                        new Point(i, ((i- contetn_topLeft.X) / Scale % Interval == 0 ? 0 : (BorderThickness.Top *2/ 3)) + content.ScrollInfo.VerticalOffset),
                        new Point(i, BorderThickness.Top + content.ScrollInfo.VerticalOffset));
                    if ((i - contetn_topLeft.X) / Scale % Interval == 0)
                        dc.DrawText(new FormattedText(((i- contetn_topLeft.X) /Scale).ToString(), new CultureInfo(""),
                            FlowDirection.LeftToRight, new Typeface("宋体"), 15, Brushes.Black), new Point(i + 3, 0+ content.ScrollInfo.VerticalOffset));
                }
            }
            if (topLeft.Y > 10)
            {//横线
                dc.DrawLine(new Pen(new SolidColorBrush(Colors.Red), 1),
                     new Point(0+ content.ScrollInfo.HorizontalOffset, _current_point.Y >= contetn_topLeft.Y ? _current_point.Y : contetn_topLeft.Y),
                     new Point(BorderThickness.Left+ content.ScrollInfo.HorizontalOffset, _current_point.Y >= contetn_topLeft.Y ? _current_point.Y : contetn_topLeft.Y));
                for (double i = contetn_topLeft.Y; i < ActualHeight+ content.ScrollInfo.VerticalOffset; i += 10)
                {
                    dc.DrawLine(new Pen(new SolidColorBrush(Colors.Black), 0.1),
                        new Point(((i - contetn_topLeft.Y) / Scale % Interval == 0 ? 0 : (BorderThickness.Left *2 / 3)) + content.ScrollInfo.HorizontalOffset, i),
                        new Point(BorderThickness.Left + content.ScrollInfo.HorizontalOffset, i));
                    if ((i - contetn_topLeft.Y) / Scale % Interval == 0)
                    {
                        dc.PushTransform(new RotateTransform() { Angle = 90 });
                        dc.DrawText(new FormattedText(((i - contetn_topLeft.Y) /Scale).ToString(), new CultureInfo(""),
                            FlowDirection.LeftToRight, new Typeface("宋体"), 15, Brushes.Black), new Point(i + 3, -15-content.ScrollInfo.HorizontalOffset));
                        dc.Pop();
                    }
                }
            }
            dc.Pop();
            dc.Pop();
        }
    }
}
